iT邦幫忙

2023 iThome 鐵人賽

DAY 10
1

文章同步於blog

介紹

今天要介紹依賴反向原則(DIP, Dependency Inversion Principle)

最靈活的系統是『原始碼的依賴關係指涉及抽象不涉及具體』
-Clean Architecture(P.75)

上述這段話的意思就是,我們應該將我的模組依賴於抽象概念
但這段話其實不切實際,特別像是Python這些大量依賴第三方套件的語言
基本上我們要做的功能已經有人幫我們做好了
甚至我們連依賴list.count()這種都屬於依賴具體物件的方法
這種情況我們不可也不該避免

所以在應用DIP時,我們可以忽略作業系統的穩定背景,我們也可以信任他們不會改變。
要注意的是,系統中容易變化的具體元素。

實作

同樣以php為例子

class Dog {
    public function bark() {
        return "汪!";
    }
}

class Cat {
    public function meow() {
        return "喵~~";
    }
}

class PetOwner {
    private $dog;
    private $cat;

    public function __construct() {
        $this->dog = new Dog();
        $this->cat = new Cat();
    }

    public function playWithPets() {
        $dogSound = $this->dog->bark();
        $catSound = $this->cat->meow();
        return "Dog: $dogSound, Cat: $catSound";
    }
}

我們可以看到PetOwner依賴於DogCat

假設未來我要多領養幾隻寵物,我就必須一直持續在petOwner裡面一直新增
持續的對petOwner做修改
萬一上層的class要做修改,那更改的範圍就會更大

換個方法

interface PetSound {
    public function makeSound();
}

class Dog implements PetSound {
    public function makeSound() {
        return "汪!";
    }
}

class Cat implements PetSound {
    public function makeSound() {
        return "喵~~";
    }
}

class PetOwner {
    private $pets = [];

    public function addPet(PetSound $pet) {
        $this->pets[] = $pet;
    }

    public function playWithPets() {
        $sounds = [];
        foreach ($this->pets as $pet) {
            $sounds[] = $pet->makeSound();
        }
        return implode(", ", $sounds);
    }
}

在這個例子中,我們引入了一個 PetSound 抽象介面,並讓 DogCat 類實現這個介面
PetOwner 類不再直接創建寵物的實例,而是通過 addPet 方法將寵物加入,並且在 playWithPets 方法中調用了抽象介面的方法。

這種做法降低了耦合度,使得我們可以較容易地擴展或修改代碼,而不會影響其他部分。這符合 DIP 原則的理念。

參考資料

Clean Architecture(ch.11)


上一篇
【Day-9】介面隔離原則(ISP)
下一篇
【Day-11】其他軟體開發原則(簡介)
系列文
軟體開發 - 程式不是會跑就好30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言